// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "AbilitySystemInterface.h"
#include "ModularPlayerState.h"
#include "System/GameplayTagStack.h"
#include "Teams/LyraTeamAgentInterface.h"

#include "LyraPlayerState.generated.h"

#define UE_API LYRAGAME_API

struct FLyraVerbMessage;

class AController;
class ALyraPlayerController;
class APlayerState;
class FName;
class UAbilitySystemComponent;
class ULyraAbilitySystemComponent;
class ULyraExperienceDefinition;
class ULyraPawnData;
class UObject;
struct FFrame;
struct FGameplayTag;

/** 定义连接的客户端类型 */
UENUM()
enum class ELyraPlayerConnectionType : uint8
{
	// 活跃玩家
	Player = 0,

	// 连接到运行中游戏的观察者
	LiveSpectator,

	// 离线观看演示录制
	ReplaySpectator,

	// 非活跃玩家（断开连接）
	InactivePlayer
};

/**
 * ALyraPlayerState
 *
 *	该项目使用的基础玩家状态类。
 */
UCLASS(MinimalAPI, Config = Game)
class ALyraPlayerState : public AModularPlayerState, public IAbilitySystemInterface, public ILyraTeamAgentInterface
{
	GENERATED_BODY()

public:
	UE_API ALyraPlayerState(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());

	UFUNCTION(BlueprintCallable, Category = "Lyra|PlayerState")
	UE_API ALyraPlayerController* GetLyraPlayerController() const;

	UFUNCTION(BlueprintCallable, Category = "Lyra|PlayerState")
	ULyraAbilitySystemComponent* GetLyraAbilitySystemComponent() const { return AbilitySystemComponent; } // 获取Lyra技能系统组件
	UE_API virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override;

	template <class T>
	const T* GetPawnData() const { return Cast<T>(PawnData); } // 获取角色数据

	UE_API void SetPawnData(const ULyraPawnData* InPawnData); // 设置角色数据

	//~AActor接口
	UE_API virtual void PreInitializeComponents() override;
	UE_API virtual void PostInitializeComponents() override;
	//~End of AActor接口

	//~APlayerState接口
	UE_API virtual void Reset() override;
	UE_API virtual void ClientInitialize(AController* C) override;
	UE_API virtual void CopyProperties(APlayerState* PlayerState) override;
	UE_API virtual void OnDeactivated() override;
	UE_API virtual void OnReactivated() override;
	//~End of APlayerState接口

	//~ILyraTeamAgentInterface接口
	UE_API virtual void SetGenericTeamId(const FGenericTeamId& NewTeamID) override;
	UE_API virtual FGenericTeamId GetGenericTeamId() const override;
	UE_API virtual FOnLyraTeamIndexChangedDelegate* GetOnTeamIndexChangedDelegate() override;
	//~End of ILyraTeamAgentInterface接口

	static UE_API const FName NAME_LyraAbilityReady; // Lyra技能准备就绪名称

	UE_API void SetPlayerConnectionType(ELyraPlayerConnectionType NewType); // 设置玩家连接类型
	ELyraPlayerConnectionType GetPlayerConnectionType() const { return MyPlayerConnectionType; } // 获取玩家连接类型

	/** 返回玩家所属小队的ID。 */
	UFUNCTION(BlueprintCallable)
	int32 GetSquadId() const
	{
		return MySquadID; // 返回小队ID
	}

	/** 返回玩家所属队伍的ID。 */
	UFUNCTION(BlueprintCallable)
	int32 GetTeamId() const
	{
		return GenericTeamIdToInteger(MyTeamID); // 返回队伍ID
	}

	UE_API void SetSquadID(int32 NewSquadID); // 设置小队ID

	// 向标签添加指定数量的堆栈（如果StackCount低于1则不执行任何操作）
	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category=Teams)
	UE_API void AddStatTagStack(FGameplayTag Tag, int32 StackCount); // 添加统计标签堆栈

	// 从标签移除指定数量的堆栈（如果StackCount低于1则不执行任何操作）
	UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category=Teams)
	UE_API void RemoveStatTagStack(FGameplayTag Tag, int32 StackCount); // 移除统计标签堆栈

	// 返回指定标签的堆栈计数（如果标签不存在则返回0）
	UFUNCTION(BlueprintCallable, Category=Teams)
	UE_API int32 GetStatTagStackCount(FGameplayTag Tag) const; // 获取统计标签堆栈计数

	// 如果标签至少有一个堆栈则返回true
	UFUNCTION(BlueprintCallable, Category=Teams)
	UE_API bool HasStatTag(FGameplayTag Tag) const; // 是否有统计标签

	// 仅向此玩家发送消息
	// （仅用于客户端通知，如荣誉、任务提示等...可以处理偶尔丢失的情况）
	UFUNCTION(Client, Unreliable, BlueprintCallable, Category = "Lyra|PlayerState")
	UE_API void ClientBroadcastMessage(const FLyraVerbMessage Message); // 客户端广播消息

	// 获取此玩家的复制视图旋转，用于观察
	UE_API FRotator GetReplicatedViewRotation() const; // 获取复制的视图旋转

	// 设置复制的视图旋转，仅在服务器上有效
	UE_API void SetReplicatedViewRotation(const FRotator& NewRotation); // 设置复制的视图旋转

private:
	UE_API void OnExperienceLoaded(const ULyraExperienceDefinition* CurrentExperience); // 经验加载回调

protected:
	UFUNCTION()
	UE_API void OnRep_PawnData(); // 角色数据复制回调

protected:

	UPROPERTY(ReplicatedUsing = OnRep_PawnData) // 复制使用OnRep_PawnData
	TObjectPtr<const ULyraPawnData> PawnData; // 角色数据

private:

	// 玩家角色使用的技能系统组件子对象。
	UPROPERTY(VisibleAnywhere, Category = "Lyra|PlayerState")
	TObjectPtr<ULyraAbilitySystemComponent> AbilitySystemComponent; // 技能系统组件

	// 此角色使用的生命值属性集。
	UPROPERTY()
	TObjectPtr<const class ULyraHealthSet> HealthSet; // 生命值集
	// 此角色使用的战斗属性集。
	UPROPERTY()
	TObjectPtr<const class ULyraCombatSet> CombatSet; // 战斗集

	UPROPERTY(Replicated) // 复制
	ELyraPlayerConnectionType MyPlayerConnectionType; // 玩家连接类型

	UPROPERTY()
	FOnLyraTeamIndexChangedDelegate OnTeamChangedDelegate; // 队伍改变委托

	UPROPERTY(ReplicatedUsing=OnRep_MyTeamID) // 复制使用OnRep_MyTeamID
	FGenericTeamId MyTeamID; // 队伍ID

	UPROPERTY(ReplicatedUsing=OnRep_MySquadID) // 复制使用OnRep_MySquadID
	int32 MySquadID; // 小队ID

	UPROPERTY(Replicated) // 复制
	FGameplayTagStackContainer StatTags; // 统计标签容器

	UPROPERTY(Replicated) // 复制
	FRotator ReplicatedViewRotation; // 复制的视图旋转

private:
	UFUNCTION()
	UE_API void OnRep_MyTeamID(FGenericTeamId OldTeamID); // 队伍ID复制回调

	UFUNCTION()
	UE_API void OnRep_MySquadID(); // 小队ID复制回调
};

#undef UE_API